﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Xml;
using System.Xml.Serialization;
using Template10.Services.NavigationService;
using Wasion.HHU.Data;
using Wasion.HHU.Data.Models;
using Wasion.HHU.Models;
using Windows.ApplicationModel.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using WsProtocol.IEC62056MDL;
using WsProtocol.IEC62056.DLL;
using static Wasion.HHU.Common.ProgramHelper;
using WsProtocol.IEC62056;
using Wasion.HHU.Services;
using Wasion.HHU.ViewModels;
using Wasion.HHU.Data.Repositories;
using System.Linq.Expressions;
using Wasion.HHU.Common;
using System.Collections.ObjectModel;
using System.ComponentModel;

// O modelo do item de página em branco está documentado em http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace Wasion.HHU.Views
{
    /// <summary>
    /// Uma página vazia que pode ser usada isoladamente ou navegada dentro de um Quadro.
    /// </summary>
    public sealed partial class Program : Page
    {
        string readMsg = "";
        SchemaDbRepository schSrv = new SchemaDbRepository();
        SchemaItemDbRepository schiSrv = new SchemaItemDbRepository();
        SchemaItemParDbRepository schipSrv = new SchemaItemParDbRepository();
        VSchItemObAttrMthDbRepository vsioaSrv = new VSchItemObAttrMthDbRepository();
        HHULogDbRepository hlSrv = new HHULogDbRepository();

        private string schId = "";
        public ObservableCollection<LVitem> ResultCollection
        {
            get;
            private set;
        }

        public Program()
        {
            this.InitializeComponent();

            if (ResultCollection == null)
            {
                ResultCollection = new ObservableCollection<LVitem>();
            }
        }

        private void BtnChoose_Click(object sender, RoutedEventArgs e)
        {
            MenuFlyout mFlyout = (MenuFlyout)Resources["SampleContextMenu"];
            BuildMenuFlyoutItem(mFlyout);
            var requestedElement = (FrameworkElement)e.OriginalSource;
            mFlyout.ShowAt(requestedElement);
        }

        private void BuildMenuFlyoutItem(MenuFlyout mf)
        {
            var schList = schSrv.GetAllList().Result;
            mf.Items.Clear();
            MenuFlyoutItem mfi;
            foreach (Schema sa in schList)
            {
                if (!string.IsNullOrEmpty(sa.SchName))
                {
                    mfi = new MenuFlyoutItem();
                    mfi.Text = sa.SchName;
                    mfi.Name = sa.ID;
                    mfi.Click += MenuItem_Click;
                    mf.Items.Add(mfi);
                }
            }
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuFlyoutItem mfi = (MenuFlyoutItem)sender;
            tbSchema.Text = mfi.Text;
            schId = mfi.Name;
            Expression<Func<VSchItemObAttrMth, bool>> filter = o => o.SchID == schId;
            var schis = vsioaSrv.GetList(filter).Result;

            foreach (VSchItemObAttrMth vsioa in schis)
            {
                ResultCollection.Add(new LVitem() { ObjId = vsioa.ObjID, Content = "名称:" + vsioa.AmName + " OBIS:" + vsioa.OBIS });
                //vsioa.
            }
            //lvSchema.ItemsSource = ResultCollection;
            //lvSchema.DisplayMemberPath = "Content";
        }

        public class LVitem : INotifyPropertyChanged
        {
            public string ObjId { get; set; }
            private string content;
            /// <summary>
            /// 内容(评价宝贝使用)
            /// </summary>
            public string Content
            {
                get
                {
                    return content;
                }
                set
                {
                    content = value;
                    if (this.PropertyChanged != null)
                    {
                        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Content"));
                    }
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string name)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));
                }
            }
        }

        private async void DisplayDialog(string title, string content)
        {
            ContentDialog dialog = new ContentDialog
            {
                Title = title,
                Content = content,
                CloseButtonText = "Ok"
            };

            ContentDialogResult result = await dialog.ShowAsync();
        }

        //private async void ReadXmlFile()
        //{
        //    Windows.Storage.Pickers.FolderPicker folderPicker = new Windows.Storage.Pickers.FolderPicker();
        //    folderPicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
        //    folderPicker.FileTypeFilter.Add(".");
        //    StorageFolder folder = await folderPicker.PickSingleFolderAsync();

        //    StorageFile xmlFile = await folder.GetFileAsync("testSch.sch");

        //    string xml;
        //    using (Stream File = await xmlFile.OpenStreamForReadAsync())
        //    {
        //        using (StreamReader read = new StreamReader(File))
        //        {
        //            xml = read.ReadToEnd();
        //        }
        //    }
        //    XmlSerializer xmlSearializer = new XmlSerializer(typeof(AllSchemas));
        //    AllSchemas allSchemas;
        //    using (StringReader sr = new StringReader(xml))
        //    {
        //        allSchemas = (AllSchemas)xmlSearializer.Deserialize(sr);
        //    }
        //    if (allSchemas != null)
        //    {
        //        using (var db = new DbConn().Connection)
        //        {
        //            foreach (XmlSchema xs in allSchemas.Schemas)
        //            {
        //                if (!string.IsNullOrEmpty(xs.ID))
        //                {
        //                    db.Insert(new Schema()
        //                    {
        //                        ID = xs.ID,
        //                        SchName = xs.SchName,
        //                        ModifiedBy = xs.ModifiedBy,
        //                        DateModified = xs.DateModified,
        //                        SchemaDesc = xs.SchemaDesc,
        //                        SchType = xs.SchType
        //                    });
        //                }
        //            }
        //        }
        //    }
        //}

        private async void ReadXmlDocument()
        {
            //Windows.Storage.Pickers.FolderPicker folderPicker = new Windows.Storage.Pickers.FolderPicker();
            //folderPicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
            //folderPicker.FileTypeFilter.Add(".");
            //StorageFolder folder = await folderPicker.PickSingleFolderAsync();

            //StorageFile xmlFile = await folder.GetFileAsync("test.sch62056");

            Windows.Storage.Pickers.FileOpenPicker filePicker = new Windows.Storage.Pickers.FileOpenPicker();
            filePicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
            filePicker.FileTypeFilter.Add("*");
            StorageFile xmlFile = await filePicker.PickSingleFileAsync();
            if (xmlFile == null)
            {
                return;
            }

            string xml;
            using (Stream sm = await xmlFile.OpenStreamForReadAsync())
            {
                using (StreamReader read = new StreamReader(sm))
                {
                    xml = read.ReadToEnd();
                }
            }
            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(xml);
            XmlNodeList xnlist = xdoc.GetElementsByTagName("T_Schema");
            if (xnlist.Count > 0)
            {
                bool ok = SaveSchema(xnlist);
                if (ok)
                {
                    xnlist = xdoc.GetElementsByTagName("T_SchemaItem");
                    if (xnlist.Count > 0)
                    {
                        SaveSchemaItem(xnlist);
                    }
                    xnlist = xdoc.GetElementsByTagName("T_SchemaItemPar");
                    if (xnlist.Count > 0)
                    {
                        SaveSchemaItemPar(xnlist);
                    }
                    DisplayDialog("Message", "Read Schema Success！");
                    return;
                }
            }
            DisplayDialog("Message", "Read Schema Fail！");
        }

        private bool SaveSchema(XmlNodeList xnList)
        {
            List<Schema> saList = new List<Schema>();

            foreach (XmlNode xn in xnList)
            {
                Schema sa = new Schema();
                XmlNodeList xncList = xn.ChildNodes;
                foreach (XmlNode xnc in xncList)
                {
                    SetValue<Schema>(sa, xnc.Name, xnc.InnerText);
                }
                saList.Add(sa);
            }
            if (saList != null && saList.Count > 0)
            {
                foreach (Schema sa in saList)
                {
                    if (!string.IsNullOrEmpty(sa.ID))
                    {
                        Schema sch = schSrv.Find(sa.ID);
                        if (sch != null)
                        {
                            return false;
                        }
                        schSrv.Insert(sa);
                    }
                }
                return true;
            }
            return false;
        }

        private void SaveSchemaItem(XmlNodeList xnList)
        {
            List<SchemaItem> schiList = new List<SchemaItem>();

            foreach (XmlNode xn in xnList)
            {
                SchemaItem sai = new SchemaItem();
                XmlNodeList xncList = xn.ChildNodes;
                foreach (XmlNode xnc in xncList)
                {
                    SetValue<SchemaItem>(sai, xnc.Name, xnc.InnerText);
                }
                schiList.Add(sai);
            }
            if (schiList != null && schiList.Count > 0)
            {
                foreach (SchemaItem si in schiList)
                {
                    if (!string.IsNullOrEmpty(si.ID))
                    {
                        SchemaItem schi = schiSrv.Find(si.ID);
                        if (schi == null)
                        {
                            schiSrv.Insert(si);
                        }
                    }
                }
            }
        }

        private void SaveSchemaItemPar(XmlNodeList xnList)
        {
            List<SchemaItemPar> schipList = new List<SchemaItemPar>();

            foreach (XmlNode xn in xnList)
            {
                SchemaItemPar saip = new SchemaItemPar();
                XmlNodeList xncList = xn.ChildNodes;
                foreach (XmlNode xnc in xncList)
                {
                    SetValue<SchemaItemPar>(saip, xnc.Name, xnc.InnerText);
                }
                schipList.Add(saip);
            }
            if (schipList != null && schipList.Count > 0)
            {
                foreach (SchemaItemPar sip in schipList)
                {
                    if (!string.IsNullOrEmpty(sip.ID))
                    {
                        SchemaItemPar schip = schipSrv.Find(sip.ID);
                        if (schip == null)
                        {
                            schipSrv.Insert(sip);
                        }
                    }
                }
            }
        }

        private void SetValue<T>(T entity, string name, string value)
        {
            if (entity == null)
            {
                throw new Exception("实体不能为空。");
            }
            decimal d = 0;
            int i = 0;
            foreach (var prop in typeof(T).GetProperties())
            {
                d = 0;
                i = 0;
                if (name.Equals(prop.Name) && value != null)
                {
                    switch (prop.PropertyType.Name)
                    {
                        case "String":
                            prop.SetValue(entity, (string)value, null);
                            break;
                        case "Decimal":
                            prop.SetValue(entity, decimal.TryParse(value, out d), null);
                            break;
                        case "Int32":
                            int.TryParse(value, out i);
                            prop.SetValue(entity, i, null);
                            break;
                        case "Int64":
                            int.TryParse(value, out i);
                            prop.SetValue(entity, i, null);
                            break;
                    }
                }
            }
        }


        private void BtnReadAnalysis_Click(object sender, RoutedEventArgs e)
        {
            ReadXmlDocument();
        }

        private void BtnReadProgram_Click(object sender, RoutedEventArgs e)
        {
            Button btn = (Button)sender;
            if (btn.Content.ToString() == "Read Program")
            {
                btn.Content = "Stop Read Program";
                ReadSetOpertion(OperaFlag.单项读取);
                DisplayDialog("Message", "Read Success！");
            }
            else
            {
                btn.Content = "Read Program";
                //funMeter.StopOperating(true);
            }
        }

        private void BtnWriteProgram_Click(object sender, RoutedEventArgs e)
        {
            Button btn = (Button)sender;
            if (btn.Content.ToString() == "Write Program")
            {
                btn.Content = "Stop Write Program";
                ReadSetOpertion(OperaFlag.单项设置);
                DisplayDialog("Message", "Write Success！");
            }
            else
            {
                btn.Content = "Write Program";
                //funMeter.StopOperating(true);
            }
        }

        /// <summary>
        /// 设置抄读处理函数，全部合一
        /// </summary>
        /// <param name="opflag"></param>
        private void ReadSetOpertion(OperaFlag opflag)
        {
            List<ProObject> Objectlst = ProObject.GetTreeObjLst();
            var list = SetSelectObject(schId, ref Objectlst);
            bool RScaler = cbReadSteel.IsChecked == null ? false : (bool)cbReadSteel.IsChecked;
            List<ProObAttr> SelNodes = PubFunc62056.GetSelectObAttr(list, RScaler, true);
            NextFramePostedDelegate NextFramePosted = new NextFramePostedDelegate(SaveDB);

            for (int i = 0; i < SelNodes.Count; i++)
            {
                PubFunc62056.FuncPreSend(SelNodes[i], opflag.ToString());   //hxh 2019-7-23 某些参数需进行组命令之前的处理                    

                Shell.Meter.MeterLst[0].Status = "设置/抄读";
                Shell.Meter.MeterLst[0].ObAttrLst.Clear();
                Shell.Meter.MeterLst[0].ObAttrLst.Add(SelNodes[i]);
                Shell.Meter.MeterLst[0].ErrInfo = string.Empty;

                switch (opflag)
                {
                    case OperaFlag.单项读取:
                        Shell.Meter.ReadData(Shell.Meter.MeterLst, NextFramePosted);
                        break;
                    case OperaFlag.单项设置:
                        if (SelNodes[i].AttrMth == AttrType.方法)
                        {
                            Shell.Meter.SetData(Shell.Meter.MeterLst, NextFramePosted);
                        }
                        else
                        {
                            Shell.Meter.SetData(Shell.Meter.MeterLst, NextFramePosted);
                        }
                        break;
                }
            }
        }

        private List<ProObject> SetSelectObject(string schId, ref List<ProObject> Objectlst)
        {
            var allProObjects = ExtensionClass.Traverse<ProObject>(Objectlst, s => s.ObjLst);

            VSchItemObAttrMthDbRepository vsoSrv = new VSchItemObAttrMthDbRepository();
            var vsoList = vsoSrv.GetList(w => w.SchID == schId).Result;

            var tmpList = new List<ProObject>();
            foreach (var proObject in allProObjects)
            {
                foreach (var obj in vsoList)
                {
                    if (proObject.ID == obj.ObjID)
                    {
                        proObject.checkState = WsProtocol.PublicClass.CheckState.Checked;
                        foreach (var item in proObject.AttrLst)
                        {
                            if (item.ID == obj.ObAttrMthID)
                            {
                                item.checkState = WsProtocol.PublicClass.CheckState.Checked;
                            }
                        }
                        tmpList.Add(proObject);
                    }
                }

            }

            return tmpList;
            //var items = Objectlst[0].ObjLst.SelectMany(x => x.ObjLst);

        }



        private void SaveDB(object testMeter, object anaPtl, ClientApduSel rwflag, string rwtype, int doflag, string errinfo)
        {
            try
            {
                Analysis62056.TProtocol62056 orderptl = (Analysis62056.TProtocol62056)anaPtl;
                TestMeter resmeter = (TestMeter)testMeter;
                List<CosemObject> OILst = orderptl.ptlformat.Apdu.OIList;
                if (OILst == null)
                {
                    return;
                }
                HHULog rb;
                for (int i = 0; i < OILst.Count; i++)
                {
                    CosemObject oiobj = OILst[i];
                    if (orderptl.ptlformat.Apdu.rwflag == ClientApduSel.ConnectRequest
                        || orderptl.ptlformat.Apdu.rwflag == ClientApduSel.DLReleaseRequest)
                    {

                        if (doflag > 0)
                        {
                            readMsg += oiobj.AmName + "  " + "成功";
                            if (oiobj.result != null && oiobj.result != "0")
                            {
                                readMsg += oiobj.AmName + "  " + oiobj.result;

                                resmeter.ErrInfo = oiobj.result;
                            }
                        }
                        else
                        {
                            readMsg += oiobj.AmName + "  " + errinfo;
                            resmeter.ErrInfo = errinfo;
                        }
                    }
                    //update 
                    var item = ResultCollection.Where(w => w.ObjId == ((ProObAttr)oiobj.Tag).ObjID).FirstOrDefault();
                    item.Content += " ReadValue:" + oiobj.DataNode.ReadValue;

                    rb = new HHULog();
                    rb.ExecutionTime = DateTime.Now.ToString();//执行方案起始时间
                    rb.ProGramName = tbSchema.Text;//方案名
                    rb.MeterNumber = resmeter.MeterNO;//表号
                    rb.MeterAddress = resmeter.MeterCommAddr;//表地址
                    ProObAttr obattr = (ProObAttr)((Analysis62056.TProtocol62056)anaPtl).ptlformat.Apdu.OIList.First().Tag;
                    rb.OBISName = ((Analysis62056.TProtocol62056)anaPtl).ptlinfo.DataName;//OBISName
                    rb.OBISValue = obattr.OBIS;//OBISValue
                    rb.RWFlag = rwflag + "|" + rwtype;//读写标志
                    rb.SetData = obattr.inputValue;//设置值
                    rb.ReadData = ((Analysis62056.TProtocol62056)anaPtl).GetReadValue();//抄读值
                    rb.UserName = "admin";//UserName 登陆用户名
                    rb.Result = readMsg;//执行是否成功标志
                    rb.Seq = int.Parse(oiobj.AttrSeq);

                    hlSrv.Insert(rb);
                }
            }
            finally
            {
            }
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {

            DataContext = this;
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {

        }
    }
}
